<template>
  <div>
    <el-upload
      ref="uploadRef"
      v-model:file-list="fileList"
      :action="action"
      :headers="headers"
      :multiple="$props.multiple"
      :limit="$props.limit"
      :accept="$props.accept"
      :before-upload="beforeUpload"
      :on-preview="handlePreview"
      :on-success="handleSuccess"
      :on-remove="handleRemove"
      list-type="picture-card"
    >
      <template #tip>
        <div class="el-upload__tip">
          {{ $props.tip }}
        </div>
      </template>

      <template #trigger>
        <el-icon><Plus /></el-icon>
      </template>
    </el-upload>

    <el-image-viewer
      :url-list="imageList"
      v-if="showImageViewer"
      @close="showImageViewer = false"
    />
  </div>
</template>

<script setup>
import { ref, computed, watchEffect } from 'vue'
import { compressorImage } from '@/utils/globalMethod'
import { deletePricture } from '@/api/globalApi'
import { userStore } from '@/pinia/user'
import { getToken } from '@/utils/auth'
import { ElMessage } from 'element-plus'

const fileList = ref([])
const uploadRef = ref()
const imageList = ref([])
const showImageViewer = ref(false)
const store = userStore()

const action = computed(() => {
  return import.meta.env.VITE_APP_BASEURL + '/upload'
})

const headers = computed(() => {
  return {
    Authorization: getToken()
  }
})

const emits = defineEmits(['uploadFile', 'update:modelValue'])

const props = defineProps({
  modelValue: {
    type: String
  },
  tip: {
    type: String
  },
  accept: {
    type: String,
    default: 'image/png, image/jpeg'
  },
  multiple: {
    type: Boolean,
    default: false
  },
  limit: {
    type: Number,
    default: 1
  }
})

watchEffect(() => {
  if (props.modelValue) {
    fileList.value = [{ name: props.modelValue, url: props.modelValue }]
  }
})

/**
 * @description: 点击上传按钮的时候触发的钩子函数
 * @return {*}
 */
const submitUpload = () => {
  uploadRef.value.submit()
}

/**
 * @description: 清除已上传的文件
 * @return {*}
 */
const clearFileList = () => {
  uploadRef.value.clearFiles()
}

defineExpose({ submitUpload, clearFileList })

/**
 * @description: 文件上传前的钩子函数，在钩子函数中对图片进行压缩处理
 * @param {*} rawFile：图片文件
 * @return {*}：压缩后的图片信息
 */
const beforeUpload = async rawFile => {
  const newFile = await compressorImage(rawFile, rawFile.name)
  return newFile
}

/**
 * @description: 删除图片的钩子函数
 * @param {*} uploadFile：删除的文件
 * @param {*} uploadFiles：删除的所有文件
 * @return {*}
 */
const handleRemove = async (uploadFile, uploadFiles) => {
  const filename = props.modelValue.split('/').pop()
  await deletePricture({ filename })
  if (uploadFiles.length === 0) {
    emits('update:modelValue', '')
  }
}

/**
 * @description: 预览钩子函数
 * @param {*} file：点击的文件
 * @return {*}
 */
const handlePreview = file => {
  imageList.value = [file?.url]
  showImageViewer.value = true
}

/**
 * @description: 上传成功的钩子函数,利用file中的status判断是否上传成功来实现整体上传进度的数据回显
 * @param {*} response：返回的响应信息
 * @param {*} uploadFile：正在上传的文件
 * @param {*} uploadFiles：正在上传的所有文件
 * @return {*}
 */
const handleSuccess = (response, uploadFile, uploadFiles) => {
  const { errno, data } = response
  if (errno === 0) {
    emits('update:modelValue', data.url)
  } else {
    ElMessage.error('上传异常！')
  }
}
</script>

<style scoped lang="scss"></style>
